﻿namespace Xenta.Events
{
    /// <summary>
    /// Exposes the event interface.
    /// </summary>
    /// <remarks>
    /// The central part of the eventing system. Events 
    /// are being published by some event source through 
    /// the event broker, the event broker dispatches an 
    /// event to subscribers for handling.
    /// </remarks>
    public interface IEvent
    {
        #region Properties

        /// <summary>
        /// Gets or sets an event marker.
        /// </summary>
        /// <remarks>
        /// The marker may be used to distinguish 
        /// the different events of the same type.
        /// </remarks>
        object Marker
        {
            get;
            set;
        }

        #endregion
    }

    /// <summary>
    /// Represents the event.
    /// </summary>
    public abstract class Event : IEvent
    {
        #region Properties

        /// <summary>
        /// Gets or sets an event marker.
        /// </summary>
        public object Marker
        {
            get;
            set;
        }

        #endregion
    }

    /// <summary>
    /// Represents the event.
    /// </summary>
    /// <typeparam name="TSource">The type of event source.</typeparam>
    public class Event<TSource> : Event
    {
        #region Fields

        private readonly TSource _source;

        #endregion

        #region Ctors

        /// <summary>
        /// Initializes a new class instance.
        /// </summary>
        /// <param name="source">The event source.</param>
        public Event(TSource source)
        {
            _source = source;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the event source.
        /// </summary>
        public TSource Source
        {
            get
            {
                return _source;
            }
        }

        #endregion
    }

    /// <summary>
    /// Represents the generic event.
    /// </summary>
    /// <typeparam name="TSource">The type of event source.</typeparam>
    /// <typeparam name="TArg">The type of argument.</typeparam>
    public class Event<TSource, TArg> : Event<TSource>
    {
        #region Fields

        private readonly TArg _arg;

        #endregion

        #region Ctors

        /// <summary>
        /// Initializes a new class instance.
        /// </summary>
        /// <param name="source">The event source.</param>
        /// <param name="arg">The event argument.</param>
        public Event(TSource source, TArg arg)
            : base(source)
        {
            _arg = arg;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the event argument.
        /// </summary>
        public TArg Arg
        {
            get
            {
                return _arg;
            }
        }

        #endregion
    }

    /// <summary>
    /// Represents the generic event.
    /// </summary>
    /// <typeparam name="TSource">The type of event source.</typeparam>
    /// <typeparam name="TArg1">The type of argument.</typeparam>
    /// <typeparam name="TArg2">The type of argument.</typeparam>
    public class Event<TSource, TArg1, TArg2> : Event<TSource, TArg1>
    {
        #region Fields

        private readonly TArg2 _arg2;

        #endregion

        #region Ctors

        /// <summary>
        /// Initializes a new class instance.
        /// </summary>
        /// <param name="source">The event source.</param>
        /// <param name="arg">The event argument.</param>
        /// <param name="arg2">The event argument 2.</param>
        public Event(TSource source, TArg1 arg, TArg2 arg2)
            : base(source, arg)
        {
            _arg2 = arg2;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the event argument 2.
        /// </summary>
        public TArg2 Arg2
        {
            get
            {
                return _arg2;
            }
        }

        #endregion
    }
}
